package com.xframe.xdal.core.util;


import cn.hutool.core.exceptions.UtilException;
import cn.hutool.core.util.ClassUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.xframe.xdal.core.annotation.XAction;
import com.xframe.xdal.core.annotation.XActionParameter;
import com.xframe.xdal.core.annotation.XColumn;
import com.xframe.xdal.core.annotation.XTable;
import com.xframe.xdal.core.domain.XDynamicModel;
import com.xframe.xdal.core.tran.XTransaction;
import lombok.extern.log4j.Log4j2;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.Validate;
import org.apache.poi.ss.usermodel.DateUtil;

import java.lang.annotation.Annotation;
import java.lang.reflect.*;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * 反射帮助类
 *
 * @author xufeng
 */
@Log4j2
public class XReflect {

    private static final String SETTER_PREFIX = "set";

    private static final String GETTER_PREFIX = "get";

    private static final String CGLIB_CLASS_SEPARATOR = "$$";


    public static Class<?> getClassByName(String typeName){
        try{
            Class<?> dataType = Class.forName(typeName);
            return dataType;
        }catch (Exception e){
            return null;
        }
    }

    /**
     * 调用Getter方法.
     * 支持多级，如：对象名.对象名.方法
     */
    @SuppressWarnings("unchecked")
    public static <E> E invokeGetter(Object obj, String propertyName) {
        Object object = obj;
        for (String name : StringUtils.split(propertyName, ".")) {
            String getterMethodName = GETTER_PREFIX + StringUtils.capitalize(name);
            object = invokeMethod(object, getterMethodName, new Class[]{}, new Object[]{});
        }
        return (E) object;
    }

    /**
     * 调用Setter方法, 仅匹配方法名。
     * 支持多级，如：对象名.对象名.方法
     */
    public static <E> void invokeSetter(Object obj, String propertyName, E value) {
        Object object = obj;
        String[] names = StringUtils.split(propertyName, ".");
        for (int i = 0; i < names.length; i++) {
            if (i < names.length - 1) {
                String getterMethodName = GETTER_PREFIX + StringUtils.capitalize(names[i]);
                object = invokeMethod(object, getterMethodName, new Class[]{}, new Object[]{});
            } else {
                String setterMethodName = SETTER_PREFIX + StringUtils.capitalize(names[i]);
                invokeMethodByName(object, setterMethodName, new Object[]{value});
            }
        }
    }



    public static <E> E getFieldValueByAttrPath(final Object obj, final String fieldName){
        String[] array = fieldName.split("\\.");
        Object curObject = obj;
        for(String attrName : array){
            curObject = getFieldValue(curObject,attrName);
            if(curObject == null){
                return null;
            }
        }
        return (E) curObject;

    }

    /**
     * 直接读取对象属性值, 无视private/protected修饰符, 不经过getter函数.
     */
    @SuppressWarnings("unchecked")
    public static <E> E getFieldValue(final Object obj, final String fieldName) {
        if(obj instanceof XDynamicModel){
            return (E) ((XDynamicModel)obj).get(fieldName);
        }
        if(obj instanceof Map){
            return (E) ((Map)obj).get(fieldName);
        }
        Field field = getAccessibleField(obj, fieldName);
        if (field == null) {
            log.info("在 [" + obj.getClass() + "] 中，没有找到 [" + fieldName + "] 字段 ");
            return null;
        }
        E result = null;
        try {
            result = (E) field.get(obj);
        } catch (IllegalAccessException e) {
            log.error("不可能抛出的异常{}", e.getMessage());
        }
        return result;
    }

    public static <E> E getFieldValue(final Object obj,Field field) {
        if (field == null) {
            return null;
        }
        E result = null;
        try {
            field.setAccessible(true);
            result = (E) field.get(obj);
        } catch (IllegalAccessException e) {
            log.error("不可能抛出的异常{}", e.getMessage());
        }
        return result;
    }

    /**
     * 直接设置对象属性值, 无视private/protected修饰符, 不经过setter函数.
     */
    public static <E> void setFieldValue(final Object obj, Field field, final E value) {
        if (field == null) {
            return;
        }
        try {
            field.setAccessible(true);
            field.set(obj, value);
        } catch (IllegalAccessException e) {
            log.error("不可能抛出的异常: {}", e.getMessage());
        }
    }

    public static void setFieldValue(final Object obj, final String fieldName, ResultSet resultSet, int index) {
        if(obj instanceof XDynamicModel){
            try {
                ((XDynamicModel)obj).set(fieldName,resultSet.getObject(index));
            } catch (SQLException e) {
                e.printStackTrace();
            }
            return;
        }
        Field field = getAccessibleField(obj, fieldName);
        if (field == null) {
            // throw new IllegalArgumentException("在 [" + obj.getClass() + "] 中，没有找到 [" + fieldName + "] 字段 ");
            log.info("在 [" + obj.getClass() + "] 中，没有找到 [" + fieldName + "] 字段 ");
            return;
        }
        try {
            Object value = null;
            if(field.getType().isAssignableFrom(Long.class)){
                value = resultSet.getLong(index);
            }else if(field.getType().isAssignableFrom(Integer.class)){
                value = resultSet.getInt(index);
            }else {
                value = resultSet.getObject(index);
            }
            field.set(obj, value);
        } catch (IllegalAccessException | SQLException e) {
            log.error("不可能抛出的异常: {}", e.getMessage());
        }
    }

    /**
     * 直接设置对象属性值, 无视private/protected修饰符, 不经过setter函数.
     */
    public static <E> void setFieldValue(final Object obj, final String fieldName, final E value) {
        if(obj instanceof XDynamicModel){
            ((XDynamicModel)obj).set(fieldName,value);
            return;
        }
        Field field = getAccessibleField(obj, fieldName);
        if (field == null) {
            // throw new IllegalArgumentException("在 [" + obj.getClass() + "] 中，没有找到 [" + fieldName + "] 字段 ");
            log.info("在 [" + obj.getClass() + "] 中，没有找到 [" + fieldName + "] 字段 ");
            return;
        }
        try {
            field.set(obj, value);
        } catch (IllegalAccessException e) {
            log.error("不可能抛出的异常: {}", e.getMessage());
        }
    }

    /**
     * 直接设置对象属性值, 无视private/protected修饰符, 不经过setter函数.
     * 支持多级，如：对象名.对象名.方法
     */
    public static void setMultistageFieldsValue(final Object obj, final String propertyName,
                                                    ResultSet resultSet, int index, final String sp, String filterStr) {

        Object object = obj;
        String filterPropertyName = propertyName.replace(filterStr,"");
        String[] names = StringUtils.split(filterPropertyName, sp);
        for (int i = 0; i < names.length; i++) {
            if (i < names.length - 1) {
                object = getFieldValueByInit(object,names[i]);
            } else {
                setFieldValue(object,names[i],resultSet,index);
            }
        }
    }

    /**
     * 直接设置对象属性值, 无视private/protected修饰符, 不经过setter函数.
     * 支持多级，如：对象名.对象名.方法
     */
    public static <E> void setMultistageFieldsValue(final Object obj, final String propertyName,
                                          final E value,final String sp,String filterStr) {

        Object object = obj;
        String filterPropertyName = propertyName.replace(filterStr,"");
        String[] names = StringUtils.split(filterPropertyName, sp);
        for (int i = 0; i < names.length; i++) {
            if (i < names.length - 1) {
                object = getFieldValueByInit(object,names[i]);
            } else {
                setFieldValue(object,names[i],value);
            }
        }
    }

    public static Object getFieldValueByInit(final Object obj, final String fieldName) {
        if(obj instanceof XDynamicModel){
            Object val = ((XDynamicModel)obj).get(fieldName);
            if(val == null){
                val = new XDynamicModel();
                ((XDynamicModel)obj).set(fieldName, val);

            }
            return val;
        }
        Field field = getAccessibleField(obj, fieldName);
        if (field == null) {
            return null;
        }
        Object result = null;
        try {
            result = field.get(obj);
            if(result == null){
                result = field.getType().newInstance();
                field.set(obj, result);
            }
        } catch (IllegalAccessException | InstantiationException e) {
            log.error("不可能抛出的异常{}", e.getMessage());
        }
        return result;
    }

    /**
     * 直接调用对象方法, 无视private/protected修饰符.
     * 用于一次性调用的情况，否则应使用getAccessibleMethod()函数获得Method后反复调用.
     * 同时匹配方法名+参数类型，
     */
    @SuppressWarnings("unchecked")
    public static <E> E invokeMethod(final Object obj, final String methodName, final Class<?>[] parameterTypes,
                                     final Object[] args) {
        //Objects.requireNonNull(other);
        //Objects.requireNonNull(obj,"111");
        if (obj == null || methodName == null) {
            return null;
        }
        Method method = getAccessibleMethod(obj, methodName, parameterTypes);
        if (method == null) {
            log.debug("在 [" + obj.getClass() + "] 中，没有找到 [" + methodName + "] 方法 ");
            return null;
        }
        try {
            return (E) method.invoke(obj, args);
        } catch (Exception e) {
            String msg = "method: " + method + ", obj: " + obj + ", args: " + args + "";
            throw convertReflectionExceptionToUnchecked(msg, e);
        }
    }

    /**
     * 直接调用对象方法, 无视private/protected修饰符，
     * 用于一次性调用的情况，否则应使用getAccessibleMethodByName()函数获得Method后反复调用.
     * 只匹配函数名，如果有多个同名函数调用第一个。
     */
    @SuppressWarnings("unchecked")
    public static <E> E invokeMethodByName(final Object obj, final String methodName, final Object[] args) {
        Method method = getAccessibleMethodByName(obj, methodName, args.length);
        if (method == null) {
            // 如果为空不报错，直接返回空。
            log.info("在 [" + obj.getClass() + "] 中，没有找到 [" + methodName + "] 方法 ");
            return null;
        }
        try {
            // 类型转换（将参数数据类型转换为目标方法参数类型）
            Class<?>[] cs = method.getParameterTypes();
            for (int i = 0; i < cs.length; i++) {
                if (args[i] != null && !args[i].getClass().equals(cs[i])) {
                    if (cs[i] == String.class) {
                        args[i] = Convert.toStr(args[i]);
                        if (StringUtils.endsWith((String) args[i], ".0")) {
                            args[i] = StringUtils.substringBefore((String) args[i], ".0");
                        }
                    } else if (cs[i] == Integer.class) {
                        args[i] = Convert.toInt(args[i]);
                    } else if (cs[i] == Long.class) {
                        args[i] = Convert.toLong(args[i]);
                    } else if (cs[i] == Double.class) {
                        args[i] = Convert.toDouble(args[i]);
                    } else if (cs[i] == Float.class) {
                        args[i] = Convert.toFloat(args[i]);
                    } else if (cs[i] == Date.class) {
                        if (args[i] instanceof String) {
                            args[i] = XDateUtil.parseDate(args[i]);
                        } else {
                            args[i] = DateUtil.getJavaDate((Double) args[i]);
                        }
                    } else if (cs[i] == boolean.class || cs[i] == Boolean.class) {
                        args[i] = Convert.toBool(args[i]);
                    }
                }
            }
            return (E) method.invoke(obj, args);
        } catch (Exception e) {
            String msg = "method: " + method + ", obj: " + obj + ", args: " + args + "";
            throw convertReflectionExceptionToUnchecked(msg, e);
        }
    }

    /**
     * 循环向上转型, 获取对象的DeclaredField, 并强制设置为可访问.
     * 如向上转型到Object仍无法找到, 返回null.
     */
    public static Field getAccessibleField(final Object obj, final String fieldName) {
        // 为空不报错。直接返回 null
        if (obj == null) {
            return null;
        }
        Validate.notBlank(fieldName, "fieldName can't be blank");
        for (Class<?> superClass = obj.getClass(); superClass != Object.class; superClass = superClass.getSuperclass()) {
            try {
                Field field = superClass.getDeclaredField(fieldName);
                makeAccessible(field);
                return field;
            } catch (NoSuchFieldException e) {
                continue;
            }
        }
        return null;
    }

    /**
     * 循环向上转型, 获取对象的DeclaredMethod,并强制设置为可访问.
     * 如向上转型到Object仍无法找到, 返回null.
     * 匹配函数名+参数类型。
     * 用于方法需要被多次调用的情况. 先使用本函数先取得Method,然后调用Method.invoke(Object obj, Object... args)
     */
    public static Method getAccessibleMethod(final Object obj, final String methodName,
                                             final Class<?>... parameterTypes) {
        // 为空不报错。直接返回 null
        if (obj == null) {
            return null;
        }
        Validate.notBlank(methodName, "methodName can't be blank");
        for (Class<?> searchType = obj.getClass(); searchType != Object.class; searchType = searchType.getSuperclass()) {
            try {
                Method method = searchType.getDeclaredMethod(methodName, parameterTypes);
                makeAccessible(method);
                return method;
            } catch (NoSuchMethodException e) {
                continue;
            }
        }
        return null;
    }


    /**
     * 查找名称方法上的XTransaction注解
     * @param method 方法对象
     *
     * @return Method
     */
    public static XTransaction getMethodTransaction(Method method){
        return getMethodAnnotation(method,XTransaction.class);
    }
    /**
     * 查找名称方法上的注解
     * @param method 方法对象
     * @param annotationClass 注解类型
     * @return Method
     */
    public static <T extends Annotation> T getMethodAnnotation(Method method,final Class<? extends Annotation> annotationClass){
        if (method.isAnnotationPresent(annotationClass)) {
            T annotation = (T) method.getAnnotation(annotationClass);
            return annotation;
        }
        return null;
    }

    /**
     * 循环向上转型, 查找名称符合的方法
     * 如向上转型到Object仍无法找到, 返回null
     * @param dataType 数据类型
     * @param methoName 方法名称
     * @return Method
     */
    public static Method getMethodByName(final Class<?> dataType,final String methoName){
        // 为空不报错。直接返回 null
        if (dataType == null) {
            return null;
        }
        // 为空不报错。直接返回 null
        if (StringUtil.isEmpty(methoName)) {
            return null;
        }
        for (Class<?> searchType = dataType; searchType != Object.class; searchType = searchType.getSuperclass()) {
            try {
                Method[] methods = searchType.getMethods();
                for (Method method : methods) {
                    // Check if the method is annotated with the specified annotation class
                    if (method.getName().equals(methoName)) {
                        // 名称相等
                        return method;
                    }
                }
            } catch (Exception e) {
                // Handle exception if needed
                continue;
            }
        }
        return null;
    }
    /**
     * 循环向上转型, 查找名称符合的方法
     * 如向上转型到Object仍无法找到, 返回null
     * @param dataType 数据类型
     * @param methoName 方法名称
     * @return Method
     */
    public static Method getMethodByName(final Class<?> dataType,final String methoName,Class<?>... parameterTypes){
        // 为空不报错。直接返回 null
        if (dataType == null) {
            return null;
        }
        // 为空不报错。直接返回 null
        if (StringUtil.isEmpty(methoName)) {
            return null;
        }

        for (Class<?> searchType = dataType; searchType != Object.class; searchType = searchType.getSuperclass()) {
            try {
                Method method = searchType.getMethod(methoName,parameterTypes);
                return method;
            } catch (Exception e) {
                // Handle exception if needed
                continue;
            }
        }
        return null;
    }
    /**
     * 循环向上转型, 查找XAction注解并且名字符合actionCode的方法并返回
     * 如向上转型到Object仍无法找到, 返回null.
     * @param dataType 数据类型
     * @param actionCode 方法名称注解code
     * @return Method
     */
    public static Method getActionMethod(final Class<?> dataType,final String actionCode){
        // 为空不报错。直接返回 null
        if (dataType == null) {
            return null;
        }
        // 为空不报错。直接返回 null
        if (StringUtil.isEmpty(actionCode)) {
            return null;
        }
        for (Class<?> searchType = dataType; searchType != Object.class; searchType = searchType.getSuperclass()) {
            try {
                Method[] methods = searchType.getMethods();
                for (Method method : methods) {
                    // Check if the method is annotated with the specified annotation class
                    if (method.isAnnotationPresent(XAction.class)) {
                        XAction xaction = method.getAnnotation(XAction.class);
                        if(xaction.code().equals(actionCode) || method.getName().equals(actionCode)){
                            return method;
                        }
                    }
                }
            } catch (Exception e) {
                // Handle exception if needed
                continue;
            }
        }
        return null;
    }

    /**
     * 获得指定Method对象上的XActionParameter 注解
     * @param method 方法对象
     *
     * @return XActionParameter 注解列表
     */
    public static List<XActionParameter> getActionParameter(final Method method){
        return getParameterAnnotations(method,XActionParameter.class);
    }

    /**
     * 根据XActionParameter注解和默认的defArgs列表来创建反射调用Method需要使用的参数数组
     * @param method 方法对象
     * @param json 参数的JSON表现形式
     * @param defArgs 默认的defArgs列表，如当前登录人信息，运行时对象等
     * @return Object[] 反射调用Method需要使用的参数数组
     */
    public static Object[] createMethodParames(Method method, String json,
                                               JSONObject requestArgsBody,
                                               Collection<Object> defArgs){
        Object[] parArray = new Object[method.getParameterCount()];
        JSONObject argsMap = JSON.parseObject(json);
        int index = 0;
        Parameter[] parameters = method.getParameters();
        for(Parameter parameter : parameters){
            XActionParameter xActionParameter = parameter.getAnnotation(XActionParameter.class);
            Class<?> pType = parameter.getType();
            Object val = null;
            try {
                if (xActionParameter == null) {
                    val = XReflect.findObjectByType(pType, defArgs);
                } else {
                    if(requestArgsBody != null){
                        val = requestArgsBody.getObject(xActionParameter.name(), pType);
                    }
                    if(val == null && argsMap != null) {
                        val = argsMap.getObject(xActionParameter.name(), pType);
                    }

                }
            }catch (Exception exception){
                exception.printStackTrace();
            }
            parArray[index] = val;
            index++;
        }
        return parArray;
    }
    /**
     * 在一个列表中根据类型来查找对象,返回类型相等的对象
     * @param type 数据类型
     * @param defArgs 默认的defArgs列表，如当前登录人信息，运行时对象等
     * @return Object 查找到的值，没有则为空
     */
    public static Object findObjectByType(Class<?> type,Collection<Object> defArgs){
        if(type == null){
            return null;
        }
        if(defArgs == null){
            return null;
        }
        for(Object object : defArgs){
            if(type.isAssignableFrom(object.getClass())){
                return object;
            }
        }
        return null;
    }

    /**
     * 获得指定Method对象上所有参数的指定注解
     * @param method 方法对象
     * @param annotationClass 注解类型
     * @return XActionParameter 注解列表
     */
    public static <E extends Annotation> List<E> getParameterAnnotations(final Method method,final Class<? extends Annotation> annotationClass){
        List<E> xActionParameterList = new ArrayList<>();
        if(method == null){
            return xActionParameterList;
        }
        Annotation[][] parameterAnnotations =  method.getParameterAnnotations();
        // 遍历参数上的注解，获取注解中的参数值
        for (Annotation[] annotations : parameterAnnotations) {
            for (Annotation annotation : annotations) {
                if (annotationClass.isAssignableFrom(annotation.annotationType())) {
                    xActionParameterList.add((E) annotation);
                }
            }
        }
        return xActionParameterList;
    }
    /**
     * 循环向上转型, 获取对象的DeclaredMethod,并强制设置为可访问.
     * 如向上转型到Object仍无法找到, 返回空数组.
     * 匹配函数名+参数类型。
     * 用于方法需要被多次调用的情况. 先使用本函数先取得Methods,然后调用Method.invoke(Object obj, Object... args)
     */
    public static Method[] getAccessibleMethods(final Class<?> dataType, final Class<? extends Annotation> annotationClass) {
        // 为空不报错。直接返回 null
        if (dataType == null) {
            return null;
        }
        List<Method> methodsWithAnnotation = new ArrayList<>();
        for (Class<?> searchType = dataType; searchType != Object.class; searchType = searchType.getSuperclass()) {
            try {
                Method[] methods = searchType.getMethods();
                for (Method method : methods) {
                    // Check if the method is annotated with the specified annotation class
                    if (method.isAnnotationPresent(annotationClass)) {
                        makeAccessible(method);
                        methodsWithAnnotation.add(method);
                    }
                }
            } catch (Exception e) {
                // Handle exception if needed
                continue;
            }
        }
        return methodsWithAnnotation.toArray(new Method[0]);
    }


    /**
     * 获取指定类型中的所以指定的注解
     * @param dataType
     * @param annotationClass
     * @return
     */
    public static Annotation[] getAccessibleAnnotations(final Class<?> dataType, final Class<? extends Annotation> annotationClass) {
        // 为空不报错。直接返回 null
        if (dataType == null) {
            return null;
        }
        List<Annotation> annotationsWithAnnotation = new ArrayList<>();
        for (Class<?> searchType = dataType; searchType != Object.class; searchType = searchType.getSuperclass()) {
            Method[] methods = searchType.getMethods();
            for (Method method : methods) {
                if (method.isAnnotationPresent(annotationClass)) {
                    Annotation[] annotationsByType = method.getAnnotationsByType(annotationClass);
                    for (Annotation annotation : annotationsByType) {
                        annotationsWithAnnotation.add(annotation);
                    }
                }
            }
        }
        return annotationsWithAnnotation.toArray(new Annotation[0]);
    }





    /**
     * 循环向上转型, 获取对象的DeclaredMethod,并强制设置为可访问.
     * 如向上转型到Object仍无法找到, 返回null.
     * 只匹配函数名。
     * 用于方法需要被多次调用的情况. 先使用本函数先取得Method,然后调用Method.invoke(Object obj, Object... args)
     */
    public static Method getAccessibleMethodByName(final Object obj, final String methodName, int argsNum) {
        // 为空不报错。直接返回 null
        if (obj == null) {
            return null;
        }
        Validate.notBlank(methodName, "methodName can't be blank");
        for (Class<?> searchType = obj.getClass(); searchType != Object.class; searchType = searchType.getSuperclass()) {
            Method[] methods = searchType.getDeclaredMethods();
            for (Method method : methods) {
                if (method.getName().equals(methodName) && method.getParameterTypes().length == argsNum) {
                    makeAccessible(method);
                    return method;
                }
            }
        }
        return null;
    }

    /**
     * 改变private/protected的方法为public，尽量不调用实际改动的语句，避免JDK的SecurityManager抱怨。
     */
    public static void makeAccessible(Method method) {
        if ((!Modifier.isPublic(method.getModifiers()) || !Modifier.isPublic(method.getDeclaringClass().getModifiers()))
                && !method.isAccessible()) {
            method.setAccessible(true);
        }
    }

    /**
     * 改变private/protected的成员变量为public，尽量不调用实际改动的语句，避免JDK的SecurityManager抱怨。
     */
    public static void makeAccessible(Field field) {
        if ((!Modifier.isPublic(field.getModifiers()) || !Modifier.isPublic(field.getDeclaringClass().getModifiers())
                || Modifier.isFinal(field.getModifiers())) && !field.isAccessible()) {
            field.setAccessible(true);
        }
    }

    /**
     * 通过反射, 获得Class定义中声明的泛型参数的类型, 注意泛型必须定义在父类处
     * 如无法找到, 返回Object.class.
     */
    @SuppressWarnings("unchecked")
    public static <T> Class<T> getClassGenricType(final Class clazz) {
        return getClassGenricType(clazz, 0);
    }

    /**
     * 通过反射, 获得Class定义中声明的父类的泛型参数的类型.
     * 如无法找到, 返回Object.class.
     */
    public static Class getClassGenricType(final Class clazz, final int index) {
        Type genType = clazz.getGenericSuperclass();

        if (!(genType instanceof ParameterizedType)) {
            log.info(clazz.getSimpleName() + "'s superclass not ParameterizedType");
            return Object.class;
        }

        Type[] params = ((ParameterizedType) genType).getActualTypeArguments();

        if (index >= params.length || index < 0) {
            log.info("Index: " + index + ", Size of " + clazz.getSimpleName() + "'s Parameterized Type: "
                    + params.length);
            return Object.class;
        }
        if (!(params[index] instanceof Class)) {
            log.info(clazz.getSimpleName() + " not set the actual class on superclass generic parameter");
            return Object.class;
        }

        return (Class) params[index];
    }

    public static Class<?> getUserClass(Object instance) {
        if (instance == null) {
            throw new RuntimeException("Instance must not be null");
        }
        Class clazz = instance.getClass();
        if (clazz != null && clazz.getName().contains(CGLIB_CLASS_SEPARATOR)) {
            Class<?> superClass = clazz.getSuperclass();
            if (superClass != null && !Object.class.equals(superClass)) {
                return superClass;
            }
        }
        return clazz;

    }

    /**
     * 将反射时的checked exception转换为unchecked exception.
     */
    public static RuntimeException convertReflectionExceptionToUnchecked(String msg, Exception e) {
        if (e instanceof IllegalAccessException || e instanceof IllegalArgumentException
                || e instanceof NoSuchMethodException) {
            return new IllegalArgumentException(msg, e);
        } else if (e instanceof InvocationTargetException) {
            return new RuntimeException(msg, ((InvocationTargetException) e).getTargetException());
        }
        return new RuntimeException(msg, e);
    }

    public static <T extends AccessibleObject> T setAccessible(T accessibleObject) {
        if (null != accessibleObject && !accessibleObject.isAccessible()) {
            accessibleObject.setAccessible(true);
        }
        return accessibleObject;
    }


    public static Class<?>[] getClasses(Object... objects) {
        Class<?>[] classes = new Class[objects.length];

        for(int i = 0; i < objects.length; ++i) {
            Object obj = objects[i];
            classes[i] = null == obj ? Object.class : obj.getClass();
        }

        return classes;
    }


    public static <T> T invoke(Object obj, String methodName, Object... args) throws UtilException {
        Method method = getAccessibleMethod(obj, methodName, getClasses(args));
        if (null == method) {
            throw new UtilException(StrUtil.format("No such method: [{}]", new Object[]{methodName}));
        } else {
            return invoke(obj, method, args);
        }
    }

    public static <T> T invoke(Object obj, Method method, Object... args){
        setAccessible(method);
        Class<?>[] parameterTypes = method.getParameterTypes();
        Object[] actualArgs = new Object[parameterTypes.length];
        if (null != args) {
            for(int i = 0; i < actualArgs.length; ++i) {
                if (i < args.length && null != args[i]) {
                    if (!parameterTypes[i].isAssignableFrom(args[i].getClass())) {
                        Object targetValue = cn.hutool.core.convert.Convert.convert(parameterTypes[i], args[i]);
                        if (null != targetValue) {
                            actualArgs[i] = targetValue;
                        }
                    } else {
                        actualArgs[i] = args[i];
                    }
                } else {
                    actualArgs[i] = ClassUtil.getDefaultValue(parameterTypes[i]);
                }
            }
        }
        try {
            return (T) method.invoke(ClassUtil.isStatic(method) ? null : obj, actualArgs);
        } catch (Exception ex) {
            log.error(ex.getMessage());
            return null;
        }
    }

    public static Map<String,Field> getFieldMap(Object bean) {
        Map<String,Field> map = new HashMap<>();
        Field[] fields = getFields(bean.getClass());
        for(Field field : fields){
            map.put(field.getName(),field);
        }
        return map;
    }


    public static <T extends Annotation>  Map<String,T> getFieldAnnotationMap(Class<?> beanType,Class<T> annotationClass) {
        Map<String,T> map = new HashMap<>();
        Field[] fields = getFields(beanType);
        for(Field field : fields){
            T[] annotations = field.getAnnotationsByType(annotationClass);
            if(annotations.length > 0) {
                map.put(field.getName(), annotations[0]);
            }
        }
        return map;
    }

    public static <T extends Annotation>  Map<String,T> getFieldAnnotationMap(Object bean,Class<T> annotationClass) {
        return getFieldAnnotationMap(bean.getClass(),annotationClass);
    }

    public static <T extends Annotation>  Map<String,T[]> getFieldAnnotationArrayMap(Class<?> beanType,Class<T> annotationClass) {
        Map<String,T[]> map = new HashMap<>();
        Field[] fields = getFields(beanType);
        for(Field field : fields){
            T[] annotations = field.getAnnotationsByType(annotationClass);
            if(annotations.length > 0) {
                map.put(field.getName(), annotations);
            }
        }
        return map;
    }
    public static <T extends Annotation>  Map<String,T[]> getFieldAnnotationArrayMap(Object bean,Class<T> annotationClass) {
        return getFieldAnnotationArrayMap(bean.getClass(),annotationClass);
    }

    public static Field[] getFields(Object bean) {
        return getFields(bean.getClass());
    }

    public static Field[] getFields(Class<?> beanClass) {
        return cn.hutool.core.util.ReflectUtil.getFields(beanClass);
    }




    private static final String DATE_FMT = "yyyy-MM-dd HH:mm:ss";

    public static Date timeToDate(Timestamp timestamp) {

        // Timestamp -> String
        SimpleDateFormat formatter = new SimpleDateFormat(DATE_FMT);
        String dateString = formatter.format(timestamp);

        // String -> Date
        Date date = new Date();
        //注意format的格式要与日期String的格式相匹配
        DateFormat sdf = new SimpleDateFormat(DATE_FMT);
        try {
            date = sdf.parse(dateString);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return date;
    }
}
